Data storage systems are arrangements of hardware and software that include storage processors coupled to arrays of non-volatile storage devices, such as magnetic disk drives, electronic flash drives, and/or optical drives, for example. The storage processors service storage requests, arriving from host machines (“hosts”), which specify files or other data elements to be written, read, created, deleted, and so forth. Software running on the storage processors manages incoming storage requests and performs various data processing tasks to organize and secure the data elements stored on the non-volatile storage devices.
Data storage systems commonly employ metadata for mapping logical addresses of files or other data elements to corresponding physical addresses in a file system or volume. For example, a file system may provide a unique inode (index node) for each file that it stores, where each inode contains a file's attributes and some of its mapping data. Each inode may point to a set of indirect blocks (IBs), which map relative offsets into the respective file (logical addresses) to corresponding locations of data blocks (physical addresses) that store the file's data in an underlying volume. The mapping metadata thus organizes the file's blocks and allows the blocks to be laid out non-contiguously, or even randomly, in the underlying volume.
Many file systems support block sharing, where the mapping metadata of multiple files point to the same data blocks. Such block sharing is common in file systems that support snaps (point-in-time versions) and deduplication (removal of redundant data blocks). Some file systems also support sharing of IBs among multiple files. For example, files that have much of their data in common may use some or all of the same IBs to map their data. To keep track of IB sharing, each IB may have a reference count, which counts the number of block pointers that point to the respective IB. For mapping large files, IBs may be arranged in a multi-level tree, where first-level IBs include block pointers to second-level IBs, which may include block pointers to third-level IBs (leaf IBs), which point to data blocks.
With this arrangement, deletion of a file or a portion thereof triggers a series of activities to reclaim the file's unshared blocks, as such blocks may be returned to circulation for reuse elsewhere in the file system. When the file system issues a request to delete a file, it may follow a block pointer in the file's inode to an IB and then decrement the IB's reference count. If the decremented reference count becomes zero, the file system may reclaim the IB, as it is no longer being used anywhere in the file system. This action may cause a ripple effect for any IBs pointed to by the reclaimed IB, as their reference counts would also be decremented and would also be reclaimed if they fell to zero. These acts may be repeated for each IB pointed to by the file's inode.